package com.finance.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.finance.entity.GoodsInventory;
import com.finance.mapper.GoodsInventoryMapper;
import com.finance.service.GoodsInventoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * C07
 * 商品进销存数据Service实现类
 */
@Slf4j
@Service
public class GoodsInventoryServiceImpl extends ServiceImpl<GoodsInventoryMapper, GoodsInventory> implements GoodsInventoryService {

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int processOrders(List<Map<String, String>> records, String searchDate, boolean forceUpdate) {
        return processOrders(records, searchDate, forceUpdate, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int processOrders(List<Map<String, String>> records, String searchDate, boolean forceUpdate, String cinemaId) {
        if (records == null || records.isEmpty()) {
            log.warn("No records to process for C07 data");
            return 0;
        }

        // 如果不是强制更新，先检查数据是否存在
        if (!forceUpdate) {
            long count = lambdaQuery()
                .eq(GoodsInventory::getSearchDate, searchDate)
                .eq(GoodsInventory::getCinemaId, cinemaId)
                .count();
            if (count > 0) {
                log.info("C07数据已存在，searchDate: {}, cinemaId: {}, 跳过处理", searchDate, cinemaId);
                return 0;
            }
        } else {
            // 如果是强制更新，先删除指定日期的数据
            lambdaUpdate()
                .eq(GoodsInventory::getSearchDate, searchDate)
                .eq(GoodsInventory::getCinemaId, cinemaId)
                .remove();
        }

        List<GoodsInventory> inventoryList = new ArrayList<>();
        for (Map<String, String> record : records) {
            try {
                GoodsInventory inventory = new GoodsInventory();
                //影院名称,影院编码,时间,货品编码,大类,大类编码,货品名称,单位
                if (StringUtils.hasText(record.get("影院名称"))) {
                    inventory.setCinemaName(record.get("影院名称"));
                }
                if (StringUtils.hasText(record.get("影院编码"))) {
                    inventory.setCinemaCode(record.get("影院编码"));
                }
                inventory.setCinemaId(cinemaId);
                // 处理操作时间
                String operationTimeStr = record.get("时间");
                if (StringUtils.hasText(operationTimeStr)) {
                    try {
                        inventory.setOperationTime(LocalDate.parse(operationTimeStr, DATE_FORMATTER));
                    } catch (Exception e) {
                        log.warn("Invalid operation time format: {}", operationTimeStr);
                    }
                }
                if (StringUtils.hasText(record.get("货品编码"))) {
                    inventory.setGoodsCode(record.get("货品编码"));
                }
                if (StringUtils.hasText(record.get("大类"))) {
                    inventory.setCategory(record.get("大类"));
                }
                if (StringUtils.hasText(record.get("大类编码"))) {
                    inventory.setCategoryCode(record.get("大类编码"));
                }
                if (StringUtils.hasText(record.get("货品名称"))) {
                    inventory.setGoodsName(record.get("货品名称"));
                }
                if (StringUtils.hasText(record.get("单位"))) {
                    inventory.setUnit(record.get("单位"));
                }
                // 处理数值类型字段
                // 期初数量,期初金额,进货数量,进货金额,返货数量,返货金额,调拨入库数量,调拨入库金额,调拨出库数量
                inventory.setInitialQuantity(parseBigDecimal(record.get("期初数量")));
                inventory.setInitialAmount(parseBigDecimal(record.get("期初金额")));
                inventory.setPurchaseQuantity(parseBigDecimal(record.get("进货数量")));
                inventory.setPurchaseAmount(parseBigDecimal(record.get("进货金额")));
                inventory.setReturnQuantity(parseBigDecimal(record.get("返货数量")));
                inventory.setReturnAmount(parseBigDecimal(record.get("返货金额")));
                inventory.setTransferInQuantity(parseBigDecimal(record.get("调拨入库数量")));
                inventory.setTransferInAmount(parseBigDecimal(record.get("调拨入库金额")));
                inventory.setTransferOutQuantity(parseBigDecimal(record.get("调拨出库数量")));
                // 调拨出库金额,调拨出库撤回数量,调拨出库撤回金额（元）,出货数量,出货金额,本期移动加权平均成本价
                inventory.setTransferOutAmount(parseBigDecimal(record.get("调拨出库金额")));
                inventory.setTransferOutCancelQuantity(parseBigDecimal(record.get("调拨出库撤回数量")));
                inventory.setTransferOutCancelAmount(parseBigDecimal(record.get("调拨出库撤回金额（元）")));
                inventory.setOutQuantity(parseBigDecimal(record.get("出货数量")));
                inventory.setOutAmount(parseBigDecimal(record.get("出货金额")));
                inventory.setWeightedCostPrice(parseBigDecimal(record.get("本期移动加权平均成本价")));
                // 耗损数量,耗损金额,销售数量,销售成本金额,盘盈亏数量,盘盈亏金额,期末数量,期末金额,损耗差异比
                inventory.setLossQuantity(parseBigDecimal(record.get("耗损数量")));
                inventory.setLossAmount(parseBigDecimal(record.get("耗损金额")));
                inventory.setSaleQuantity(parseBigDecimal(record.get("销售数量")));
                inventory.setSaleCostAmount(parseBigDecimal(record.get("销售成本金额")));
                inventory.setInventoryDiffQuantity(parseBigDecimal(record.get("盘盈亏数量")));
                inventory.setInventoryDiffAmount(parseBigDecimal(record.get("盘盈亏金额")));
                inventory.setFinalQuantity(parseBigDecimal(record.get("期末数量")));
                inventory.setFinalAmount(parseBigDecimal(record.get("期末金额")));
                inventory.setLossDiffRatio(parseBigDecimal(record.get("损耗差异比")));
                inventory.setSearchDate(searchDate);

                // 处理含税金额字段
                inventory.setInitialAmountWithTax(parseBigDecimal(record.get("期初金额（含税）")));
                inventory.setPurchaseAmountWithTax(parseBigDecimal(record.get("进货金额（含税）")));
                inventory.setReturnAmountWithTax(parseBigDecimal(record.get("返货金额（含税）")));
                inventory.setTransferInAmountWithTax(parseBigDecimal(record.get("调拨入库金额（含税）")));
                inventory.setTransferOutAmountWithTax(parseBigDecimal(record.get("调拨出库金额（含税）")));
                inventory.setTransferOutCancelAmountWithTax(parseBigDecimal(record.get("调拨出库撤回金额（含税）")));
                inventory.setOutAmountWithTax(parseBigDecimal(record.get("出货金额（含税）")));
                inventory.setLossAmountWithTax(parseBigDecimal(record.get("耗损金额（含税）")));
                inventory.setSaleCostAmountWithTax(parseBigDecimal(record.get("销售成本金额（含税）")));
                inventory.setInventoryDiffAmountWithTax(parseBigDecimal(record.get("盘盈亏金额（含税）")));
                inventory.setFinalAmountWithTax(parseBigDecimal(record.get("期末金额（含税）")));
                inventory.setLossDiffRatioWithTax(parseBigDecimal(record.get("损耗差异比（含税）")));

                inventoryList.add(inventory);
            } catch (Exception e) {
                log.error("Error processing C07 record: {}", record, e);
                throw new RuntimeException("Failed to process C07 record", e);
            }
        }

        try {
            saveBatch(inventoryList);
            return inventoryList.size();
        } catch (Exception e) {
            log.error("Error saving C07 data batch", e);
            throw new RuntimeException("Failed to save C07 data batch", e);
        }
    }

    /**
     * 解析字符串为BigDecimal
     * @param value 字符串值
     * @return BigDecimal对象，如果解析失败则返回null
     */
    private BigDecimal parseBigDecimal(String value) {
        if (!StringUtils.hasText(value)) {
            return null;
        }
        try {
            return new BigDecimal(value.trim());
        } catch (NumberFormatException e) {
            log.warn("Failed to parse BigDecimal from value: {}", value);
            return null;
        }
    }
} 